/****************************************************************************
 * Copyright (c) 2008, 2010 Andreas Unger and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Andreas Unger - initial API and implementation 
 ****************************************************************************/

package org.eclipselabs.damos.dml.services;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipselabs.damos.dml.DMLPlugin;
import org.eclipselabs.damos.dml.internal.services.BlockTypeDescriptorImpl;

/**
 * @author Andreas Unger
 *
 */
public class BlockTypeService {

	private static final String EXTENSION_POINT_NAME = "blockTypes";
	private static final String LISTENER_ELEMENT = "blockType";
	private static final String ID_ATTRIBUTE = "id";
	private static final String NAME_ATTRIBUTE = "name";
	private static final String URI_ATTRIBUTE = "uri";
	private static final String GROUP_ATTRIBUTE = "group";

	private static BlockTypeService instance;
	private Map<String, BlockTypeDescriptor> blockTypes;
	
	/**
	 * 
	 */
	private BlockTypeService() {
	}
	
	public static BlockTypeService getInstance() {
		if (instance == null) {
			instance = new BlockTypeService();
		}
		return instance;
	}
	
	public Collection<BlockTypeDescriptor> getBlockTypeDescriptors() {
		if (blockTypes == null) {
			loadBlockTypes();
		}
		return blockTypes.values();
	}

	public BlockTypeDescriptor getBlockTypeDescriptor(String id) {
		if (blockTypes == null) {
			loadBlockTypes();
		}
		return blockTypes.get(id);
	}
	
	private void loadBlockTypes() {
		blockTypes = new HashMap<String, BlockTypeDescriptor>();

		IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(
				DMLPlugin.PLUGIN_ID, EXTENSION_POINT_NAME);

		for (IExtension extension : extensionPoint.getExtensions()) {
			for (IConfigurationElement configurationElement : extension.getConfigurationElements()) {
				if (LISTENER_ELEMENT.equals(configurationElement.getName())) {
					try {
						String id = getRequiredAttribute(configurationElement, ID_ATTRIBUTE);
						String name = getRequiredAttribute(configurationElement, NAME_ATTRIBUTE);
						String uriString = getRequiredAttribute(configurationElement, URI_ATTRIBUTE);
						String groupString = getRequiredAttribute(configurationElement, GROUP_ATTRIBUTE);

						URI uri = URI.createURI(uriString);
						BlockGroupDescriptor group = BlockGroupService.getInstance().getBlockGroupDescriptor(groupString);
						if (group == null) {
							throw new IllegalArgumentException("Block group '" + groupString + "' not found");
						}
						BlockTypeDescriptorImpl blockType = new BlockTypeDescriptorImpl();
						blockType.setId(id);
						blockType.setName(name);
						blockType.setUri(uri);
						blockType.setGroup(group);
						blockTypes.put(id, blockType);
					} catch (Exception e) {
						DMLPlugin.INSTANCE.getPluginLogger().log(
								new Status(IStatus.ERROR, DMLPlugin.PLUGIN_ID,
										"Failed to load block type in plug-in '"
										+ extension.getContributor().getName()
										+ "' in extension of '"
										+ extensionPoint.getUniqueIdentifier()
										+ "'", e));
					}
				}
			}
		}

	}
	
	private String getRequiredAttribute(IConfigurationElement configurationElement, String name) {
		String value = configurationElement.getAttribute(name);
		if (value == null) {
			throw new IllegalArgumentException("Missing '" + name + "' attribute");
		}
		return value;
	}
	
}
